from .redis_db import RedisDB
import redis
import time

KEY_NAME_DF_ENV_NAMES = "df-env-names"
DF_ENV_TIMEOUT = 3600 * 24
ENVS_LIST_KEY = "env_uuids"


class DFEnvInfo(RedisDB):


    def get_envs_key_info(self):
        '''
        [{
            "prefix": "12346",
            "names": [$env_name]
        },]
        '''
        envs = []
        conn = redis.Redis(connection_pool=self.conn_pool)
        envs_prefixs = conn.lrange(ENVS_LIST_KEY, 0, -1)
        for prefix in envs_prefixs:
            env = {}
            env["prefix"] = prefix.decode('utf-8')
            list_key_name = f"{env['prefix']}-{KEY_NAME_DF_ENV_NAMES}"
            env_names = conn.lrange(list_key_name, 0, -1)
            env["names"] = [name.decode('utf-8') for name in env_names]
            envs.append(env)
        return envs

    def get_prefix_envs(self, prefix=""):
        list_key_name = f"{prefix}-{KEY_NAME_DF_ENV_NAMES}"
        conn = redis.Redis(connection_pool=self.conn_pool)
        env_names = conn.lrange(list_key_name, 0, -1)
        envs = {}
        for name in env_names:
            name = name.decode('utf-8')
            env = conn.hgetall(name)
            if env:
                env_decode = {}
                for k, v in env.items():
                    env_decode[k.decode('utf-8')] = v.decode('utf-8')
                envs[name] = env_decode
        return envs

    def init_envs(self, envs, prefix=""):
        """
        envs = [{
            "name": "df-ce-0",
            "status": "0",
            "mgt_ip": "10.1.19.1",
            "updated_time": "1600000000",
            "type": "deepflow",
        }]
        """
        conn = redis.Redis(connection_pool=self.conn_pool)
        list_key_name = f"{prefix}-{KEY_NAME_DF_ENV_NAMES}"
        env_names_key = conn.lrange(list_key_name, 0, -1)
        for env in envs:
            env_name:str = env['name']
            # env list
            if env_name.encode('utf-8') not in env_names_key:
                conn.lpush(list_key_name, env_name)
            # env metadata
            conn.hmset(env_name, env)
            # env timeout
            conn.expire(env_name, DF_ENV_TIMEOUT)
        # List timeout reset
        conn.expire(list_key_name, DF_ENV_TIMEOUT)
        envs_prefixs = conn.lrange(ENVS_LIST_KEY, 0, -1)
        if prefix.encode('utf-8') not in envs_prefixs:
            conn.lpush(ENVS_LIST_KEY, prefix)

    def update(self, env_name, info: dict):
        update = False
        conn = redis.Redis(connection_pool=self.conn_pool)
        for k, v in info.items():
            if conn.hget(env_name, k) != v:
                conn.hset(env_name, k, v)
                update = True
        if update:
            updated = int(time.time())
            conn.hset(env_name, "updated_time", updated)

    def update_env_reserved(self, env_name, reserved):
        conn = redis.Redis(connection_pool=self.conn_pool)
        conn.hset(env_name, "reserved", reserved)
        updated = conn.hget(env_name, "updated_time")
        updated = int(time.time())
        conn.hset(env_name, "updated_time", updated)

    def update_env_status(self, env_name, status):
        conn = redis.Redis(connection_pool=self.conn_pool)
        conn.hset(env_name, "status", status)
        updated = conn.hget(env_name, "updated_time")
        updated = int(time.time()) - int(updated)
        conn.hset(env_name, "updated_time", updated)

    def update_env_concurrency(self, env_name, concurrency):
        conn = redis.Redis(connection_pool=self.conn_pool)
        conn.hset(env_name, "concurrency", concurrency)
        updated = conn.hget(env_name, "updated_time")
        updated = int(time.time()) - int(updated)
        conn.hset(env_name, "updated_time", updated)

    def get_update_time(self, env_name):
        conn = redis.Redis(connection_pool=self.conn_pool)
        updated = conn.hget(env_name, "updated_time")
        return int(updated)

    def delete_env(self, prefix):
        print(f"delete env {prefix}")
        conn = redis.Redis(connection_pool=self.conn_pool)
        # get envs list
        list_key_name = f"{prefix}-{KEY_NAME_DF_ENV_NAMES}"
        env_names = conn.lrange(list_key_name, 0, -1)
        for name in env_names:
            name = name.decode('utf-8')
            conn.delete(name)

        # delete env key list
        conn.delete(list_key_name)

        # delete env uuid
        conn.lrem(ENVS_LIST_KEY, 0, prefix)

    def delete_by_instance_name(self, prefix, instance_name):
        list_key_name = f"{prefix}-{KEY_NAME_DF_ENV_NAMES}"
        conn = redis.Redis(connection_pool=self.conn_pool)
        env_names = conn.lrange(list_key_name, 0, -1)
        for name in env_names:
            name = name.decode('utf-8')
            if name == instance_name:
                conn.delete(name)
        conn.lrem(list_key_name, 0, instance_name)

    def clear(self):
        conn = redis.Redis(connection_pool=self.conn_pool)
        conn.flushdb()
